package com.ruoyi.business.youdaoController.shangyou;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.protobuf.util.JsonFormat;
import com.ruoyi.business.services.HttpService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.SaveType;
import com.ruoyi.common.utils.EncrypDES;
import com.ruoyi.common.utils.GetUrlParam;
import com.ruoyi.common.utils.OtherUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.domain.vo.R;
import com.ruoyi.system.protocol.IDynamicSearchService;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;

/**
 * WIFI->快手
 */
@RestController
@RequestMapping("ownWfToKsApi")
public class WFToKSController {


    @Autowired
    private RedisCache redisCache;

    @Autowired
    private HttpService httpService;
    @Autowired
    private IDynamicSearchService dynamicSearchService;

    private final static String CLASSESEN = "youdao";


    //wifi回调地址
    private final static String CALLBACK_URLBASE = "http://c2.wkanx.com/tracking";


    /**
     * wifi -> 快手RTA
     * http://www.ssptqt.com/ownWfToKsApi/rta?channelId=&dmpid=__SID__&idfa=__IDFA__&idfamd5=__HASH_IDFA__&imei=__IMEI__&imeimd5=__HASH_IMEI__&oaid=__OAID__&oaidmd5=__HASH_OAID__
     * @param request
     * @return
     * @throws Exception
     */
    @Log(title = "有道", businessType = BusinessType.RTA, esIndex = "youdao_log", saveType = SaveType.ES)
    @RequestMapping("/rta")
    public Object rtaSend(HttpServletRequest request) throws Exception {
        String queryString = request.getQueryString();
        String channelId = request.getParameter("channelId");
        String dmpid = request.getParameter("dmpid");
        if(StringUtils.isBlank(channelId) || "null".equals(channelId)){
            return R.failure().msg("channelId不能为空");
        }
        if(StringUtils.isBlank(dmpid) || "null".equals(dmpid)){
            return R.failure().msg("dmpid不能为空");
        }

        Map<String, Object> baseParamsMap = GetUrlParam.queryStrToMap(queryString);

        baseParamsMap.remove("channelId");
        //注意- 这个地方不要删除dmpid. 作为请求唯一标识传入快手rta中！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！
//        baseParamsMap.remove("dmpid");

        Map<String, Object> channelDetail = redisCache.getCacheMapValue(CLASSESEN+"Cache", channelId);
        if(channelDetail == null){
            return R.failure().msg("channelId不正确");
        }
        String url = channelDetail.get("rta_adress") + "";
        String requestAddress = GetUrlParam.getRequestAddress(url);
        String staticParameters = GetUrlParam.TruncateUrlPage(url);
        Map<String, Object> staticParamsMap = GetUrlParam.queryStrToMap(staticParameters);
        baseParamsMap.putAll(staticParamsMap);

        String reportResultsStr = "";
        reportResultsStr = sendProtobufRequest(requestAddress, baseParamsMap);
        JSONObject reportResults = null;
        try {
            reportResults = JSONObject.parseObject(reportResultsStr);
            redisCache.setCacheMapValue(dmpid+"_Cache", "rtaResult", reportResults);
            if(!reportResults.containsKey("statusCode") || reportResults.getInteger("statusCode") == 0){
                JSONArray jsonArray = reportResults.getJSONArray("promotionResult");
                Boolean accept = jsonArray.getJSONObject(0).getBoolean("accept");
                if(accept != null && accept){
//                    return 1;
                    return new JSONObject().fluentPut("errcode", 0).fluentPut("errinfo", "success").fluentPut("result", true).fluentPut("rta_id_list", new ArrayList<>(Arrays.asList(channelId)));
                }
//                return 0;
                return new JSONObject().fluentPut("errcode", 0).fluentPut("errinfo", "success").fluentPut("result", false).fluentPut("rta_id_list", new ArrayList<>(Arrays.asList(channelId)));
            }
//            return 0;
            return new JSONObject().fluentPut("errcode", 0).fluentPut("errinfo", "success").fluentPut("result", false).fluentPut("rta_id_list", new ArrayList<>(Arrays.asList(channelId)));
        }catch (Exception e){
            e.printStackTrace();
        }
//        return 0;
        return new JSONObject().fluentPut("errcode", 0).fluentPut("errinfo", "success").fluentPut("result", false).fluentPut("rta_id_list", new ArrayList<>(Arrays.asList(channelId)));
    }

    public String sendProtobufRequest(String url, Map<String, Object> params) throws Exception {
//        String url = "https://material-api.test.gifshow.com/rest/n/rta/common/kfy";  // 测试环境
//        String requestId = "00000298d27e48be9d4bb2180395357b";  // 请求Id
//        String channel = "QUANNENG";  // 渠道标识，需向快手技术申请
//        String token = "Abcdefg";  // 渠道标识令牌
        //promotionType 推广类型
        String channel = getMapValue(params, "channel"); //向快手申请
        String requestId = getMapValue(params, "dmpid");
        String token = getMapValue(params, "token");//向快手申请
        String idfa = getMapValue(params, "idfa");
        String idfaMd5 = getMapValue(params, "idfa_md5");
        String imei = getMapValue(params, "imei");
        String imeimd5 = getMapValue(params, "imeimd5");
        String oaid = getMapValue(params, "oaid");
        String oaidmd5 = getMapValue(params, "oaidmd5");
        String promotionType = getMapValue(params, "promotionType");//向快手确认


        // 构建请求
        ask.RtaRequestOuterClass.RtaRequest.Builder builder = ask.RtaRequestOuterClass.RtaRequest.newBuilder();
        builder.setRequestId(requestId);
        builder.setChannel(channel);
        long requestTime = System.currentTimeMillis();
        builder.setRequestTime(requestTime);
        String sign = requestId + requestTime + token;
        String signKey = DigestUtils.md5DigestAsHex(sign.getBytes()).toLowerCase();
        builder.setSign(signKey);

        // 构建设备标识
        ask.RtaRequestOuterClass.RtaRequest.Device.Builder deviceBuilder = ask.RtaRequestOuterClass.RtaRequest.Device.newBuilder();
        deviceBuilder.setIdfa(idfa);
        deviceBuilder.setIdfaMd5(idfaMd5);

        deviceBuilder.setImei(imei);
        deviceBuilder.setImeiMd5(imeimd5);

        deviceBuilder.setOaid(oaid);
        deviceBuilder.setOaidMd5(oaidmd5);

        builder.setDevice(deviceBuilder.build());
        builder.addPromotionType(promotionType);

        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost request = new HttpPost(url);
        request.addHeader("content-type", "application/x-protobuf");
        request.setEntity(new ByteArrayEntity(builder.build().toByteArray()));
        CloseableHttpResponse response = client.execute(request);
        client.close();
        // 解析响应
        HttpEntity entity = response.getEntity();
        byte[] bytes = EntityUtils.toByteArray(entity);
        ask.RtaRequestOuterClass.RtaResponse rtaResponse = ask.RtaRequestOuterClass.RtaResponse.parseFrom(bytes);
        String res = JsonFormat.printer().print(rtaResponse);
        return res;
    }




    /**
     * https://www.ssptqt.com/ownWfToKsApi/send?
     * channelId=7067983893792768&dmpid=__SID__&cid=__CID__&idfa=__PLAIN_IDFA__&idfa_md5=__IDFA__&imeimd5=__IMEI__&oaid=__OAID__&imei=__PLAIN_IMEI__&mac=__MAC__&timestamp=__STIME__&os=__OS__&android_id=__ANDROID_ID__&ip=&ua=
     * wifi->快手
     * @param request
     * @return
     * @throws Exception
     */
    @Log(title = "有道", businessType = BusinessType.ESCALATION, esIndex = "youdao_log", saveType = SaveType.ES)
    @RequestMapping("/send")
    public Object send(HttpServletRequest request) throws Exception {
        String queryString = request.getQueryString();
        String channelId = request.getParameter("channelId");
        String dmpid = request.getParameter("dmpid");
        if(StringUtils.isBlank(channelId) || "null".equals(channelId)){
            return R.failure().msg("channelId不能为空");
        }
        if(StringUtils.isBlank(dmpid) || "null".equals(dmpid)){
            return R.failure().msg("dmpid不能为空");
        }

        Map<String, Object> baseParamsMap = GetUrlParam.queryStrToMap(queryString);

        baseParamsMap.remove("channelId");
        baseParamsMap.remove("dmpid");

        Map<String, Object> channelDetail = redisCache.getCacheMapValue(CLASSESEN+"Cache", channelId);
        if(channelDetail == null){
            return R.failure().msg("channelId不正确");
        }
        String url = channelDetail.get("request_address") + "";
        String requestType = channelDetail.get("request_type") + "";
        String requestAddress = GetUrlParam.getRequestAddress(url);
        String staticParameters = GetUrlParam.TruncateUrlPage(url);
        Map<String, Object> staticParamsMap = GetUrlParam.queryStrToMap(staticParameters);
        baseParamsMap.putAll(staticParamsMap);

        String ua = baseParamsMap.get("ua") + "";
        String ip = baseParamsMap.get("ip") + "";
        if(StringUtils.isNotBlank(ua) && !"null".equals(ua)){
            ua = URLDecoder.decode(ua, Constants.UTF8);
        }else{
            //request 获取 ua
            ua = request.getHeader("User-Agent");
            baseParamsMap.put("ua", URLEncoder.encode(ua, Constants.UTF8));
        }
        if(StringUtils.isNotBlank(ip) && !"null".equals(ip)){
        }else{
            //request 获取 ip
            ip = IpUtils.getIpAddr(request);
            baseParamsMap.put("ip", ip);
        }

        String callbackClientId = channelDetail.get("callback_clientid") + "";
        String callbackSecretkey = channelDetail.get("callback_secretkey") + "";

        String os = getMapValue(baseParamsMap, "os");

        LinkedHashMap<String, String> callbackMap = new LinkedHashMap<>();
        callbackMap.put("cid", getMapValue(baseParamsMap, "cid"));
        callbackMap.put("clientid", callbackClientId);
        callbackMap.put("clientkey", callbackSecretkey);
        callbackMap.put("idfa", getMapValue(baseParamsMap, "idfa_md5"));
        callbackMap.put("imei", getMapValue(baseParamsMap, "imeimd5"));
        //下游的mac是进行MD5加密过的就是上游的mac_md5
        callbackMap.put("mac", getMapValue(baseParamsMap, "mac"));
        callbackMap.put("os", os);
        //sid代表请求标识
        callbackMap.put("sid", dmpid);
        //stime为上报时间戳。 上传过来的参数为ts
        callbackMap.put("stime", getMapValue(baseParamsMap, "timestamp"));

        List<String> tempList = new ArrayList<>();
        for(String key: callbackMap.keySet()){
            tempList.add(key+"="+callbackMap.get(key));
        }
        String callbackParams = String.join("&", tempList);
        EncrypDES encrypDES = new EncrypDES();
        String callbackBase = OtherUtils.getServerUrl(request) + "ownWfToKsApi/callback/"+channelId+"/"+dmpid+"/";
        callbackBase = callbackBase.replace("http://", "https://");
        String encrypt_u = encrypDES.encrypt(CALLBACK_URLBASE);
        String nu = callbackBase + encrypt_u + "?"+callbackParams;

        baseParamsMap.put("os", os.equals("0")?"ANDROID":os.equals("1")?"IOS":"OTHERS");
        baseParamsMap.put("ts", baseParamsMap.get("timestamp"));
        baseParamsMap.put("callback_url", URLEncoder.encode(nu, Constants.UTF8));



        Map<String, Object> baseParamsMapTemp = new HashMap<>();
        baseParamsMapTemp.put("adid", baseParamsMap.get("adid"));//url中配置
        baseParamsMapTemp.put("click_id", dmpid);
        baseParamsMapTemp.put("imei", baseParamsMap.get("imei"));
        baseParamsMapTemp.put("idfa", baseParamsMap.get("idfa"));
        baseParamsMapTemp.put("oaid", baseParamsMap.get("oaid"));
        baseParamsMapTemp.put("mac", baseParamsMap.get("mac"));
        baseParamsMapTemp.put("android_id", baseParamsMap.get("android_id"));
        baseParamsMapTemp.put("ip", baseParamsMap.get("ip"));
        baseParamsMapTemp.put("user_agent", baseParamsMap.get("ua"));
        baseParamsMapTemp.put("callback", baseParamsMap.get("callback_url"));


        tempList = new ArrayList<>();
        for(String key: baseParamsMapTemp.keySet()){
            String val = baseParamsMapTemp.get(key) + "";
            if(val.startsWith("_") && val.endsWith("_")){
                val = "";
            }
            tempList.add(key+"="+val);
        }
        String requestParameters = String.join("&", tempList);

        String uuid = IdUtils.fastSimpleUUID();
        String reqType = "click";
        if("POST".equals(requestType)){
            httpService.sendPost(requestAddress, requestParameters, ip, ua, uuid, reqType);
        }else{
            httpService.sendGet(requestAddress, requestParameters, ip, ua, uuid, reqType);
        }
        return R.success().msg(uuid);
    }


    @Log(title = "有道", businessType = BusinessType.CALLBACK, esIndex = "youdao_log", saveType = SaveType.ES)
    @RequestMapping("/callback/{channelId}/{dmpid}/{encryptedUrl}")
    public Object callback(HttpServletRequest request, @PathVariable("encryptedUrl") String encryptedUrl) throws Exception {
        String queryString = request.getQueryString();
        Map<String, Object> queryMap = GetUrlParam.queryStrToMap(queryString);
        String eventType = queryMap.get("actionType") + "";

        if("1".equals(eventType)) {
            queryMap.put("event_type", 1);
        }else if("2".equals(eventType)){
            queryMap.put("event_type", 5);
        }else {
            queryMap.put("event_type", 1);
        }

        LinkedHashMap<String, String> callbackMap = new LinkedHashMap<>();
        callbackMap.put("cid", getMapValue(queryMap, "cid"));
        callbackMap.put("clientid", getMapValue(queryMap, "clientid"));

        callbackMap.put("idfa", getMapValue(queryMap, "idfa"));
        //下游没有imei, 但是有imei_md5
        callbackMap.put("imei", getMapValue(queryMap, "imei"));
        //下游的mac是进行MD5加密过的就是上游的mac_md5
        callbackMap.put("mac", getMapValue(queryMap, "mac"));
        callbackMap.put("os", getMapValue(queryMap, "os"));
        //sid是下游给的click_id。 代表请求标识
        callbackMap.put("sid", getMapValue(queryMap, "sid"));
        //stime为上报时间戳。 上传过来的参数为ts
        callbackMap.put("stime", getMapValue(queryMap, "stime"));
        //获取当前时间戳 并转化为秒
        callbackMap.put("ts", (System.currentTimeMillis()/1000)+"");

        String callbackSecretkey = getMapValue(queryMap, "clientkey");
        List<String> tempList = new ArrayList<>();
        for(String key: callbackMap.keySet()){
            tempList.add(key+"="+callbackMap.get(key));
        }
        String callbackParams = String.join("&", tempList);
        String md5 = DigestUtils.md5DigestAsHex((callbackParams+callbackSecretkey).getBytes(Constants.UTF8)).toUpperCase();
        callbackParams = callbackParams + "&event_type="+getMapValue(queryMap, "event_type");
        queryString = callbackParams + "&sign="+md5;

        EncrypDES encrypDES = new EncrypDES();
        String requestAddress = encrypDES.decrypt(encryptedUrl);

        String uuid = IdUtils.fastSimpleUUID();
        String reqType = "callback";
        httpService.sendGet(requestAddress, queryString, null, null, uuid, reqType);
//        return R.success();
        //{
        // "ret":0, // 0 为成功
        // "msg":"", // 如 code 不为 0，请填写错误信息
        // "data":{
        // "":"" // 可自定义
        // }
        //}
        JSONObject res = new JSONObject();
        res.put("ret", 0);
        res.put("msg", "");
        res.put("data", new JSONObject());
        return res;
    }


    private String getMapValue(Map<String, Object> map, String key){
        if(map == null){
            return "";
        }
        if(map.get(key) == null){
            return "";
        }
        String val = map.get(key) + "";
        if(val.startsWith("_") && val.endsWith("_")){
            return "";
        }
        return val;
    }

}
